Skip to content

feat(creation): Implement joint account creation flow#517

Open
yasin-ce wants to merge 14 commits intomultisig/06-account-pages-supportfrom
multisig/07-creation-flow
Open

feat(creation): Implement joint account creation flow#517
yasin-ce wants to merge 14 commits intomultisig/06-account-pages-supportfrom
multisig/07-creation-flow

Conversation

@yasin-ce
Copy link
Copy Markdown
Collaborator

Summary

  • Add AddAccountIntroFragment with create joint account option
  • Add NameJointAccountFragment for account naming
  • Add AddJointAccountFragment for participant selection
  • Add SetThresholdFragment for threshold configuration
  • Add CreateJointAccountFragment for final creation
  • Add CreateJointAccountUseCase with validation
  • Add JointAccountInfoDialog for feature explanation
  • Add JointAccountSignRequestFragment for sign request handling
  • Add PendingSignaturesBottomSheet for signature status
  • Add JointAccountLedgerSignHelper for Ledger device signing

Test Plan

  • Create joint account with 2 participants, threshold 2
  • Create joint account with 3 participants, threshold 2
  • Verify participant validation (no duplicates, valid addresses)
  • Verify threshold validation (≤ participant count)
  • Test Ledger participant signing flow
  • Test contact creation for external addresses

@yasin-ce yasin-ce self-assigned this Jan 20, 2026
@yasin-ce yasin-ce force-pushed the multisig/06-account-pages-support branch from 4b6f926 to f44cf3b Compare January 20, 2026 09:32
@yasin-ce yasin-ce force-pushed the multisig/07-creation-flow branch from 5b34bb9 to 9fa3c15 Compare January 20, 2026 09:32
@yasin-ce yasin-ce force-pushed the multisig/06-account-pages-support branch from f44cf3b to c787611 Compare January 20, 2026 09:49
@yasin-ce yasin-ce force-pushed the multisig/07-creation-flow branch from 9fa3c15 to 91daf6f Compare January 20, 2026 09:49
- Fix duplicate DI bindings for joint account repository
- Add missing interface implementations
- Update transaction signer handling for joint accounts
- Fix import statements and code organization
- Add CreateJointAccountFragment and ViewModel
- Add NameJointAccountFragment for account naming
- Add AddJointAccountFragment for participant selection
- Implement JointAccountTransactionSignHelper
- Add CreateJointAccountUseCase
- Add participant selection UI components
- Handle contact creation for external addresses
- Update AccountAssetsFragment to use onInboxClick
- Update AccountAssetsAccountDetailAdapter to call listener.onInboxClick
- Update AccountDetailQuickActionsView to match Inbox sealed class
@yasin-ce yasin-ce force-pushed the multisig/06-account-pages-support branch from c787611 to 8bd9179 Compare January 20, 2026 13:49
@yasin-ce yasin-ce force-pushed the multisig/07-creation-flow branch from 91daf6f to ab2aecc Compare January 20, 2026 13:49
…ation-flow

* multisig/06-account-pages-support:
  fix(di): Add missing GetJointAccount and GetJointAccountParticipantCount bindings
  fix(test): Use correct domain model class names in HasInboxItemsForAddressUseCaseTest
Architecture:
- app module (UI only): Fragments, Screens, ViewModels that use interfaces
- common-sdk domain layer (public): UseCase interfaces, Domain models
- common-sdk data layer (internal): Repository (internal), UseCase implementations, Services, Mappers

Changes:
- Make JointAccountRepository internal
- Create use case interfaces for each repository function:
  - CreateJointAccount
  - GetInboxMessages
  - DeleteInboxJointInvitationNotification
- Create internal use case implementations
- Delete duplicate data layer from app module
- Update app module to use common-sdk use cases
- Add Dagger bindings for new use cases
Fix Fragment lifecycle violations where initSavedStateListener was called
in onResume instead of onViewCreated:

- ContactInfoFragment: Remove duplicate call in onResume (was in both)
- AccountHistoryFragment: Move to onViewCreated
- Arc59SendSummaryFragment: Move to onViewCreated, remove empty onResume
- InAppPinFragment: Move to onViewCreated, remove empty onResume

This ensures SavedState listeners are registered early in the lifecycle
and prevents missing initial state emissions.
…tion

The existing GetInboxMessages in InboxUseCases.kt gets cached data.
The new FetchInboxMessages fetches from the API via repository.
- Replace *DTO suffix with actual domain model names
- ParticipantSignatureDTO -> ParticipantSignature
- JointSignRequestDTO -> JointSignRequest
- SignRequestWithFullSignatureDTO -> SignRequestWithFullSignature
- TransactionListWithFullSignatureDTO -> TransactionListWithFullSignature
- SignRequestTransactionListResponseDTO -> AddSignatureInput
- Fix PeraResult.Success/Error usage in DefaultJointAccountDetailProcessor
private val isThereAnyLocalAccount: IsThereAnyLocalAccount
) : GetAddAccountIntroPreview {

override fun invoke(isShowingCloseButton: Boolean): Flow<AddAccountIntroPreview> = flow {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary flow. We can return the result as AddAccountIntroPreview

import com.algorand.android.R
import javax.inject.Inject

class AddAccountIntroPreviewDecider @Inject constructor() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move these functions in mapper

sealed interface ViewState {
data object Idle : ViewState
data class Content(
val preview: AddAccountIntroPreview
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove preview class move fields here

fun onSearchQueryUpdate(query: String) {
stateDelegate.updateState { it.copy(searchQuery = query) }
searchJob?.cancel()
searchJob = viewModelScope.launch {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use flow.debounce instead of creating scope and waiting


fun getAccountSelectionList(
query: String,
): Flow<List<JointAccountSelectionListItem>> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these functions are not observing flows, they are just getting results as flow. There is no point of returning flow here as well as using combine function. you can simply return the result. This is creating unnecessary flows each time query is updated

mainActivity?.showAlertSuccess(
title = getString(R.string.account_has_been_added),
description = null,
tag = this::class.simpleName.orEmpty()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function's default tag parameter is already set, no need to set the same parameter

}
}

override suspend fun hasSigningCapableLocalAccount(address: String): Boolean {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical issue

}
val contact = contactRepository.getContactByAddress(address)
val localAccount = getLocalAccount(address)
val isLedger = localAccount is LocalAccount.LedgerBle
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical issue

participantData.localParticipants.isEmpty() ||
!hasUnsigned

return JointAccountTransactionPreview(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ViewState instead of preview

}

companion object {
private const val MIN_PARTICIPANTS_COUNT = 2
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use existing JointAccount constant for this

@mitsinsar mitsinsar mentioned this pull request Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants